import type { Teacher, Classroom, Student, Course, Schedule } from '../SchedulingManagementPage';

// 智能排课算法实现
class SchedulingAlgorithm {
  private teachers: Teacher[];
  private classrooms: Classroom[];
  private students: Student[];
  private courses: Course[];

  constructor(teachers: Teacher[], classrooms: Classroom[], students: Student[], courses: Course[]) {
    this.teachers = teachers;
    this.classrooms = classrooms;
    this.students = students;
    this.courses = courses;
  }

  // 运行排课算法
  async run(): Promise<Schedule[]> {
    const schedules: Schedule[] = [];
    
    // 按优先级排序课程
    const sortedCourses = [...this.courses].sort((a, b) => b.priority - a.priority);
    
    // 为每个课程分配时间、教师和教室
    for (const course of sortedCourses) {
      const schedule = this.scheduleCourse(course, schedules);
      if (schedule) {
        schedules.push(schedule);
      }
    }
    
    return schedules;
  }

  // 为单个课程排课
  private scheduleCourse(course: Course, existingSchedules: Schedule[]): Schedule | null {
    // 获取课程所需的教师
    const teacher = this.teachers.find(t => t.id === course.teacherId);
    if (!teacher) return null;

    // 获取课程所需的教室
    const classroom = this.classrooms.find(c => c.id === course.requiredClassroom);
    if (!classroom) return null;

    // 获取课程所需的学生
    const requiredStudents = this.students.filter(s => course.requiredStudents.includes(s.id));
    if (requiredStudents.length === 0) return null;

    // 尝试在教师、教室和学生都可用的时间段安排课程
    const availableTimeSlots = this.findAvailableTimeSlots(teacher, classroom, requiredStudents, existingSchedules, course.duration);
    
    if (availableTimeSlots.length === 0) {
      // 如果没有找到完美匹配，尝试寻找次优解
      return this.findAlternativeTimeSlot(course, existingSchedules, teacher, classroom, requiredStudents);
    }

    // 选择第一个可用的时间段
    const timeSlot = availableTimeSlots[0];
    
    // 创建排课记录
    return {
      id: `schedule-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
      courseId: course.id,
      teacherId: teacher.id,
      classroomId: classroom.id,
      studentIds: course.requiredStudents,
      startTime: timeSlot.startTime,
      endTime: timeSlot.endTime,
      day: timeSlot.day,
    };
  }

  // 查找所有可用的时间段
  private findAvailableTimeSlots(
    teacher: Teacher,
    classroom: Classroom,
    students: Student[],
    existingSchedules: Schedule[],
    duration: number
  ): Array<{ startTime: string; endTime: string; day: string }> {
    const availableSlots: Array<{ startTime: string; endTime: string; day: string }> = [];
    
    // 一周的上课日
    const weekdays = ['周一', '周二', '周三', '周四', '周五'];
    
    // 每天的上课时间段（假设为9:00-12:00, 14:00-17:00）
    const dailySlots = [
      { start: '09:00', end: '12:00' },
      { start: '14:00', end: '17:00' },
    ];
    
    // 生成可能的时间段
    for (const day of weekdays) {
      for (const slot of dailySlots) {
        const startTime = new Date();
        const endTime = new Date();
        
        // 设置日期和时间
        // 实际项目中这里应根据当前学期设置正确的日期
        
        // 检查时间段是否可用
        if (this.isTimeSlotAvailable(startTime, endTime, day, teacher, classroom, students, existingSchedules)) {
          availableSlots.push({
            startTime: startTime.toISOString(),
            endTime: endTime.toISOString(),
            day,
          });
        }
      }
    }
    
    return availableSlots;
  }

  // 检查时间段是否可用
  private isTimeSlotAvailable(
    startTime: Date,
    endTime: Date,
    day: string,
    teacher: Teacher,
    classroom: Classroom,
    students: Student[],
    existingSchedules: Schedule[]
  ): boolean {
    // 检查教师是否可用
    if (!teacher.availableTimeSlots.some(slot => slot.includes(day))) {
      return false;
    }
    
    // 检查教室是否可用
    if (!classroom.availableTimeSlots.some(slot => slot.includes(day))) {
      return false;
    }
    
    // 检查学生是否可用
    for (const student of students) {
      if (!student.availableTimeSlots.some(slot => slot.includes(day))) {
        return false;
      }
    }
    
    // 检查是否与现有排课冲突
    for (const schedule of existingSchedules) {
      // 检查教师冲突
      if (schedule.teacherId === teacher.id && this.isTimeOverlap(startTime, endTime, new Date(schedule.startTime), new Date(schedule.endTime))) {
        return false;
      }
      
      // 检查教室冲突
      if (schedule.classroomId === classroom.id && this.isTimeOverlap(startTime, endTime, new Date(schedule.startTime), new Date(schedule.endTime))) {
        return false;
      }
      
      // 检查学生冲突
      for (const studentId of schedule.studentIds) {
        if (students.some(s => s.id === studentId) && this.isTimeOverlap(startTime, endTime, new Date(schedule.startTime), new Date(schedule.endTime))) {
          return false;
        }
      }
    }
    
    return true;
  }

  // 检查时间是否重叠
  private isTimeOverlap(start1: Date, end1: Date, start2: Date, end2: Date): boolean {
    return start1 < end2 && start2 < end1;
  }

  // 寻找次优解（允许部分冲突，但尝试最小化）
  private findAlternativeTimeSlot(
    course: Course,
    existingSchedules: Schedule[],
    teacher: Teacher,
    classroom: Classroom,
    students: Student[]
  ): Schedule | null {
    // 简化版：随机选择一个时间段，实际项目中应实现更复杂的算法
    const days = ['周一', '周二', '周三', '周四', '周五'];
    const day = days[Math.floor(Math.random() * days.length)];
    
    const startTime = new Date();
    const endTime = new Date();
    // 实际项目中这里应设置合理的时间
    
    return {
      id: `schedule-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
      courseId: course.id,
      teacherId: teacher.id,
      classroomId: classroom.id,
      studentIds: course.requiredStudents,
      startTime: startTime.toISOString(),
      endTime: endTime.toISOString(),
      day,
    };
  }
}

export default SchedulingAlgorithm;